from rest_framework import filters
from rest_framework import permissions
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
from rest_framework.views import APIView
from rest_framework import viewsets

import re
from django.contrib.auth.models import User, Group, Permission, ContentType
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth.decorators import login_required, permission_required
from django.utils.timezone import now
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q

from .models import *
from .serializers import *
from tool import restful
from tool.paginations import CommonPagination
from rewrite.my_modelviewset import MyModelViewSet
from rewrite.my_mixins import MyListModelMixin

from tool.getrandom import guess
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager



# 用户存在判断：忘记密码,注册时验证
class Exists(MyModelViewSet):
    """
    用户存在判断
    """
    # queryset = User.objects.get(realname = )
    serializer_class = UserExistsSerializer
    def get_queryset(self, *args, **kwargs):
        # print('加入验证')
        username = self.request.query_params.get("username")
        telephone = self.request.query_params.get("telephone")
        if username:
            return User.objects.filter(username__exact=username)
        elif telephone:
            return User.objects.filter(telephone__exact=str(telephone))
        else:
            return User.objects.filter(id=0)

# 用户外部注册
class Register(MyModelViewSet):
    """
    用户注册：最好添加邮箱认证或手机号认证
    """
    serializer_class = UserExistsSerializer
    def get_queryset(self, *args, **kwargs):
        # print('加入验证')
        username = self.request.query_params.get("username")
        telephone = self.request.query_params.get("telephone")
        password = self.request.query_params.get("password")
        realname = self.request.query_params.get("realname")
        sex = self.request.query_params.get("sex")
        invite = self.request.query_params.get("invite")
        
        if username and telephone and password and realname and sex:
            haveuser1 = User.objects.filter(username__exact=username).first()
            haveuser2 = User.objects.filter(telephone__exact=str(telephone)).first()
            if haveuser1 or haveuser2:
                return restful.unauthorized('账号或手机号已存在！')
            else:
                # 处理密码
                # password = make_password(password)
                # 处理性别
                if sex == '男' or sex == 'gg' or sex == 'man' or sex == 'boy' :
                    sex = 'male'
                else:
                    sex= 'female'
                # 设置用户权限
                # is_staff = False # 人工核查信息后才给权限
                is_staff = True
                is_active = True
                projects = ',1,'
                modules= ',1,3,4,5,6,7,8,9,10,'
                # 处理头像
                por = Portrait()
                if sex == 'female':
                    por.portrait = r'img/portraits/girl.png'
                else:
                    por.portrait = r'img/portraits/boy.png'
                por.save()
                # 处理邀请码
                if invite:
                    theinvite = Invite.objects.filter(invite__exact=str(invite)).first()
                    if theinvite:
                        theinvite.usetime = theinvite.usetime + 1
                        if theinvite.usetime <= 10:
                            theinvite.save()
                            invite = theinvite
                        else:
                            invite = None
                    else:
                        invite = None
                else:
                    invite = None
                newuser = User(username=username, realname=realname, sex=sex, password=password, telephone=telephone, 
                               portrait=por, invite=invite, is_staff=is_staff, is_active=is_active, projects=projects, modules=modules)
                newuser.set_password(password)
                newuser.save()
                
                # thisnewuser = User.objects.filter(username__exact=username)
                # 重写相应
                serializer = User.objects.filter(username__exact=username)
                context = {
                    'code': status.HTTP_201_CREATED,
                    'msg': '注册成功！',
                    'data': serializer
                }
                return context
                # return thisnewuser
                # return Response({'message': '创建成功','data':serializer}, status=201)
        return restful.unauthorized('信息不完整！')
             
            # return User.objects.filter(username__exact=username)
        # elif telephone:
        #     return User.objects.filter(telephone__exact=str(telephone))
        # else:
        #     return User.objects.filter(id=0)
    # queryset = User.objects.filter(id=0)
    # serializer_class = UserSerializer
    # def get_queryset(self, *args, **kwargs):
    #     # print('加入验证')
    #     username = self.request.query_params.get("username")
    #     if username:
    #         return User.objects.filter(username__exact=username)
    #     else:
    #         return User.objects.filter(id=0)
    # def create(self, request, *args, **kwargs):
    #     """
    #     创建一个用户模型的实例.
    #     """
    #     # 在存储密码前，截取数据，调用原生函数加密密码
    #     # 因为不能修改QueryDict ，使用特殊方法保存加密密码
    #     data = request.data
    #     # 记住旧的方式
    #     # _mutable = data._mutable
    #     # 设置_mutable为True
    #     # data._mutable = True
    #     # 改变你想改变的数据
    #     data['password'] = make_password(data["password"])
    #     # 设置用户权限
    #     # data['is_staff'] = False # 人工核查信息后才给权限
    #     data['is_staff'] = True
    #     data['is_active'] = True
    #     data['projects'] = ',1,'
    #     data['modules'] = ',1,3,4,5,6,7,8,9,10,'
    #     # 设置用户头像
    #     data['portrait'] = ''

    #     if "sex" in data:
    #         if request.data['sex'] == '男':
    #             request.data['sex'] = 'male'
    #         elif request.data['sex'] == '女':
    #             request.data['sex'] = 'female'
    #         sex = request.data["sex"]
    #         por = Portrait()
    #         if sex == 'female':
    #             por.portrait = r'img/portraits/girl.png'
    #         else:
    #             por.portrait = r'img/portraits/boy.png'
    #         por.save()
    #         data['portrait'] = por
    #     # 恢复_mutable原来的属性
    #     # data._mutable = _mutable
    #     serializer = self.get_serializer(data=request.data)
    #     serializer.is_valid(raise_exception=True)
    #     serializer.save()

    #     if "username" in request.data:
    #         serializer.instance.username = request.data["username"]
    #     if "realname" in request.data:
    #         serializer.instance.realname = request.data["realname"]
    #     if 'portrait' in request.data:
    #         serializer.instance.portrait = request.data["portrait"]
    #     if "telephone" in request.data:
    #         serializer.instance.telephone = request.data["telephone"]
    #     if "sex" in request.data:
    #         serializer.instance.sex = request.data["sex"]
    #     if "idcard" in request.data:
    #         serializer.instance.idcard = request.data["idcard"]
    #     if "address" in request.data:
    #         serializer.instance.address = request.data["address"]
    #     if "invite" in request.data:
    #         serializer.instance.invite = request.data["invite"]
    #     if "birthday" in request.data:
    #         serializer.instance.birthday = request.data["birthday"]

    #     # if "projects" in request.data:
    #     #     serializer.instance.projects = request.data["projects"]
    #     # if "modules" in request.data:
    #     #     serializer.instance.modules = request.data["modules"]
    #     serializer.instance.save()
    #     serializer.save()
    #     headers = self.get_success_headers(serializer.data)
    #     context = {
    #         'code': status.HTTP_201_CREATED,
    #         'msg': '创建成功！',
    #         'data': serializer.data
    #     }
    #     return Response(context, status=status.HTTP_201_CREATED, headers=headers)


# 登录相关
# 获取Token
class Login(TokenObtainPairView):
    """
    获取Token
    """
    serializer_class = MyTokenObtainPairSerializer
    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        try:
            # 如果验证错误，在这里中断了进程，如果要在验证错误时返回内容，需在Serializer重写is_valid
            serializer.is_valid(raise_exception=True)
            serializer.validated_data['code'] = status.HTTP_200_OK
            user = User.objects.filter(username=request.data['username']).first()
            # return Response(serializer.validated_data, status=status.HTTP_200_OK)
            data = {
                'token': serializer.validated_data['access'],
                # 'user_id': user.pk,
                'user_name': user.username,
                'is_superuser': user.is_superuser,
                'email': user.email,
                'perms': user.get_all_permissions(),
            }
            return restful.success('登录成功！', data)
        except:
            return restful.unauthorized('账号或密码错误！')

    
# 用户管理相关
# 个人信息
class UserSelfViewSet(MyModelViewSet):
    """
    用户个人信息<br>
    """
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self, *args, **kwargs):
        return User.objects.filter(username__exact=self.request.user.username)
# 用户管理
class UserViewSet(MyModelViewSet):
    """
    用户列表<br>
    通过获取搜索参数查找用户<br>
    search输入工号精确查找<br>
    search输入姓名,或部门名模糊查找<br>
    """
    # queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = CommonPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    def get_queryset(self, *args, **kwargs):
        search = self.request.query_params.get("search")
        group = self.request.query_params.get("group")
        permission = self.request.query_params.get("permission")
        # 设置容器承载分组用户集和权限用户集
        users_group = []
        users_permission = []
        # 如果传了这两个参数，把参数处理成用户集
        if group:
            group = int(group)
            users = Group.objects.filter(id=group).first().user_set.all()
            for user in users:
                users_group.append(user.pk)
        if permission:
            permission = int(permission)
            users = Permission.objects.filter(id=permission).first().user_set.all()
            for user in users:
                users_permission.append(user.pk)
            groups = Permission.objects.filter(id=permission).first().group_set.all()
            for group in groups:
                users = group.user_set.all()
                for user in users:
                    users_permission.append(user.pk)
        # 逻辑判断
        if search and group and permission:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search)).filter(pk__in=users_group).filter(
                pk__in=users_permission)
        elif search and group:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search)).filter(pk__in=users_group)
        elif search and permission:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search)).filter(pk__in=users_permission)
        elif group and permission:
            return User.objects.filter(is_active__exact='1').filter(pk__in=users_group).filter(pk__in=users_permission)
        elif search:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search))
        elif group:
            return User.objects.filter(is_active__exact='1').filter(pk__in=users_group)
        elif permission:
            return User.objects.filter(is_active__exact='1').filter(pk__in=users_permission)
        else:
            return User.objects.filter(is_active__exact='1')
    def create(self, request, *args, **kwargs):
        """
        创建一个用户模型的实例.
        """
        # 在存储密码前，截取数据，调用原生函数加密密码
        request.data["password"] = make_password(request.data["password"])
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        if "username" in request.data:
            serializer.instance.username = request.data["username"]
        if "realname" in request.data:
            serializer.instance.realname = request.data["realname"]
        if 'portrait' in request.data:
            serializer.instance.portrait = request.data["portrait"]
        if "telephone" in request.data:
            serializer.instance.telephone = request.data["telephone"]
        if 'sex' in request.data:
            if request.data['sex'] == '男':
                request.data['sex'] = 'male'
            elif request.data['sex'] == '女':
                request.data['sex'] = 'female'
            serializer.instance.sex = request.data["sex"]
            sex = request.data["sex"]
            por = Portrait()
            if sex == 'female':
                por.portrait = r'img/portraits/girl.png'
            else:
                por.portrait = r'img/portraits/boy.png'
            por.save()
            serializer.instance.portrait = por
        if "idcard" in request.data:
            serializer.instance.idcard = request.data["idcard"]
        if "address" in request.data:
            serializer.instance.address = request.data["address"]
        if "invite" in request.data:
            serializer.instance.invite = request.data["invite"]
        if "birthday" in request.data:
            serializer.instance.birthday = request.data["birthday"]
        if "is_staff" in request.data:
            serializer.instance.is_staff = request.data["is_staff"]
        if "is_active" in request.data:
            serializer.instance.is_active = request.data["is_active"]
        if "group" in request.data:
            groups = request.data["group"]
            for group in groups:
                thisgroup = Group.objects.get(id=int(group))
                serializer.instance.groups.add(thisgroup)
        serializer.instance.save()
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        context = {
            'code': status.HTTP_201_CREATED,
            'msg': '创建成功！',
            'data': serializer.data
        }
        return Response(context, status=status.HTTP_201_CREATED, headers=headers)
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)
    def update(self, request, *args, **kwargs):
        """
        更新一个模型的实例.
        """
        if 'sex' in request.data:
            if request.data['sex'] == '男':
                request.data['sex'] = 'male'
            elif request.data['sex'] == '女':
                request.data['sex'] = 'female'
        if 'password' in request.data:
            request.data["password"] = make_password(request.data["password"])
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(
            instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)
        if getattr(instance, '_prefetched_objects_cache', None):
            instance._prefetched_objects_cache = {}
        context = {
            'code': status.HTTP_200_OK,
            'msg': '更新成功！',
            'data': serializer.data
        }
        return Response(context)
    def perform_destroy(self, instance):
        instance.delete()
# 用户下拉选
class UserOptionViewSet1(MyModelViewSet):# 无真实名，用于用户间查询
    """
    用户列表<br>
    通过获取搜索参数查找用户<br>
    search输入工号精确查找<br>
    search输入姓名,或部门名模糊查找<br>
    """
    # queryset = User.objects.all()
    serializer_class = UserOptionSerializer1
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = CommonPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]

    def get_queryset(self, *args, **kwargs):
        search = self.request.query_params.get("search")
        if search:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search))
        else:
            return User.objects.filter(is_active__exact='1')
class UserOptionViewSet2(MyModelViewSet):# 有真实名，用于管理查询
    """
    用户列表<br>
    通过获取搜索参数查找用户<br>
    search输入工号精确查找<br>
    search输入姓名,或部门名模糊查找<br>
    """
    # queryset = User.objects.all()
    serializer_class = UserOptionSerializer2
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = CommonPagination
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]

    def get_queryset(self, *args, **kwargs):
        search = self.request.query_params.get("search")
        if search:
            return User.objects.filter(is_active__exact='1').filter(
                Q(username__exact=search) | Q(realname__icontains=search))
        else:
            return User.objects.filter(is_active__exact='1')


# 头像
# 用户头像上传、更新API
class PortraitViewSet(MyModelViewSet):
    """
    用户头像上传、更新API
    """
    queryset = Portrait.objects.filter(deleted__exact='0')
    serializer_class = PortraitSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]


# 历史地址
# 历史地址API
class AddressHistoricalViewSet(MyModelViewSet):
    """
    历史地址API
    """
    queryset = AddressHistorical.objects.filter(deleted__exact='0')
    serializer_class = AddressHistoricalSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]


# 地址管理
class AddressViewSet(MyModelViewSet):
    """
    地址管理API
    """
    queryset = Address.objects.filter(deleted__exact='0')
    serializer_class = AddressSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]
class AddressOptionViewSet(MyModelViewSet):
    """
    地址管理下拉选API
    """
    queryset = Address.objects.filter(deleted__exact='0')
    serializer_class = AddressOptionSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]

# 标签管理
class LabelViewSet(MyModelViewSet):
    """
    标签管理API
    """
    queryset = Label.objects.filter(deleted__exact='0')
    serializer_class = LabelSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]
class LabelOptionViewSet(MyModelViewSet):
    """
    标签管理下拉选API
    """
    queryset = Label.objects.filter(deleted__exact='0')
    serializer_class = LabelOptionSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]
class LabelToUserViewSet(MyModelViewSet):
    """
    标签指向用户API
    """
    queryset = LabelToUser.objects.filter(deleted__exact='0')
    serializer_class = LabelToUserSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]
class LabelToUserOptionViewSet(MyModelViewSet):
    """
    标签指向用户下拉选API
    """
    queryset = LabelToUser.objects.filter(deleted__exact='0')
    serializer_class = LabelToUserOptionSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]


# 邀请码
class InviteViewSet(MyModelViewSet):
    """
    邀请码API
    """
    queryset = Invite.objects.filter(deleted__exact='0')
    serializer_class = InviteSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]


# 用户忘记密码
class UserForgetViewSet(MyModelViewSet):
    queryset = UserForget.objects.filter(id=0)
    serializer_class = UserForgetSerializer
    def create(self, request, *args, **kwargs):
        """
        创建一个模型的实例.
        """
        # print('this')
        if 'username' in request.data and 'telephone' in request.data:
            thisuser1 = User.objects.get(username=request.data['username'])
            thisuser2 = User.objects.get(telephone=str(request.data['telephone']))
            if thisuser1 and thisuser2:
                if thisuser1 == thisuser2:
                    actions = UserForget.objects.filter(who=thisuser1)
                    if actions:
                        for action in actions:
                            action.deleted = '1'
                            action.save()
                    request.data['who'] = thisuser1.id
                else:
                    return restful.unauthorized('账号和注册手机不一致！')
            else:
                return restful.unauthorized('账号或注册手机号不存在！')
        else:
            return restful.unauthorized('账号或注册手机号未填写！')
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        headers = self.get_success_headers(serializer.data)
        context = {
            'code': status.HTTP_201_CREATED,
            'msg': '创建成功！',
            'data': serializer.data
        }
        return Response(context, status=status.HTTP_201_CREATED, headers=headers)


# 用户信息
class DataToUserViewSet(MyModelViewSet):
    """
    用户信息API
    """
    queryset = DataToUser.objects.filter(deleted__exact='0')
    serializer_class = DataToUserSerializer
    pagination_class = CommonPagination
    permission_classes = [permissions.IsAuthenticated]


# 分组 权限
# 用户分组
class GroupViewSet(MyModelViewSet):
    """
    用户分组<br>
    操作传参，不管是更新还是创建都需要提供<br>
    name：权限分组名<br>
    group_permission：权限ID数组列表<br>
    user_set：用户ID数组列表<br>
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

    def create(self, request, *args, **kwargs):
        """
        创建一个模型的实例.
        """
        # 截取未序列化数据
        group_permission = request.data['group_permission']
        users_items = request.data['user_set']

        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # 获取权限列表给分组赋予权限
        for permission in group_permission:
            if permission != '':
                permissions = Permission.objects.get(id=int(permission))
                # 遍历添加权限
                serializer.instance.permissions.add(permissions)
        serializer.save()
        # 获取用户列表给分组加入用户
        for user in users_items:
            if user != '':
                thisuser = User.objects.get(id=int(user))
                thisuser.groups.add(serializer.instance)
                thisuser.save()
        serializer.save()

        headers = self.get_success_headers(serializer.data)
        context = {
            'code': status.HTTP_201_CREATED,
            'msg': '创建成功！',
            'data': serializer.data
        }
        # czj第一个修改点
        user = self.request.user
        obj = serializer.instance
        new_action = Action(objectType=obj.__class__.__name__.lower(
        ), objectID=obj.pk, system='patrol', actor=user.username, action='create', date=now(), read=0)
        new_action.save()

        return Response(context, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, *args, **kwargs):
        """
        更新一个模型的实例.
        """
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        group_permission = []
        users_items = []
        if 'group_permission' in request.data:
            group_permission = request.data['group_permission']
        if 'user_set' in request.data:
            users_items = request.data['user_set']
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            instance._prefetched_objects_cache = {}
        if group_permission != []:
            # 清空之前的权限
            serializer.instance.permissions.clear()
            # 从新分配权限
            for permission in group_permission:
                if permission != '':
                    permissions = Permission.objects.get(id=int(permission))
                    # 遍历添加权限
                    serializer.instance.permissions.add(permissions)
        if users_items != []:
            # 清空在这个分组的所有用户
            all_user = User.objects.all()
            for this_user in all_user:
                this_user.groups.remove(serializer.instance)
                this_user.save()
            # 获取用户列表给分组加入用户
            for user in users_items:
                if user != '':
                    thisuser = User.objects.get(id=int(user))
                    thisuser.groups.add(serializer.instance)
                    thisuser.save()
        serializer.save()
        context = {
            'code': status.HTTP_200_OK,
            'msg': '更新成功！',
            'data': serializer.data
        }
        return Response(context)

    def destroy(self, request, *args, **kwargs):
        """
        销毁模型实例.
        """
        instance = self.get_object()
        # 永久删除
        self.perform_destroy(instance)
        context = {
            'code': status.HTTP_204_NO_CONTENT,
            'msg': '删除成功！',
            'data': ''
        }
        # 如果反馈“HTTP_204_NO_CONTENT”，会导致context中内容没有返回给浏览器
        return Response(context, status=status.HTTP_200_OK)
# 权限分组下拉选
class GroupOptionViewSet(MyModelViewSet):
    """
    分组下拉选
    """
    queryset = Group.objects.all()
    serializer_class = GroupOptionSerializer
    permission_classes = [permissions.IsAuthenticated]
# 权限下拉选
class PermissionOptionViewSet(MyModelViewSet):
    """权限下拉选"""
    queryset = Permission.objects.all()
    serializer_class = PermissionOptionSerializer
    permission_classes = [permissions.IsAuthenticated]




